import type { Position } from '@turf/turf'
import type {
  MapToolBarPropsType,
  MapToolBarEventStateType,
  MapToolBarLngLatType,
  MapToolBarEventMethod
} from './typings'
import { reactive, nextTick } from 'vue'
import {
  lineString,
  lineSplit,
  polygon,
  booleanWithin,
  lineIntersect,
  booleanContains
} from '@turf/turf'
// import { ElMessage } from 'element-plus'
import styles from './index.module.scss'

export default function useToolbarEventHook(
  props: MapToolBarPropsType,
  setCurrentPatternPath: (pattern: Record<string, any>) => void
): [eventState: MapToolBarEventStateType, eventMethod: MapToolBarEventMethod] {
  const eventState = reactive<MapToolBarEventStateType>({})

  const polylineOptions = {
    lineJoin: 'round',
    lineCap: 'round',
    strokeOpacity: 1,
    strokeWeight: 4,
    isOutline: false,
    bubble: true
  }

  const eventMethod: MapToolBarEventMethod = {
    // 为地图绑定设置全屏操作
    handleMapBindFullFrame(visible, callback) {
      const { screenDomRef } = props
      if (visible) {
        const requestMethod =
          screenDomRef.value.requestFullScreen ||
          screenDomRef.value.webkitRequestFullScreen ||
          screenDomRef.value.mozRequestFullScreen ||
          screenDomRef.value.msRequestFullScreen
        if (requestMethod) requestMethod.call(screenDomRef.value)
        const timer = setTimeout(() => {
          document.addEventListener('fullscreenchange', callback, { once: true })
          clearTimeout(timer)
        }, 500)
        return
      }
      if (document.fullscreenElement) {
        document.exitFullscreen()
      } else {
        document.documentElement.requestFullscreen()
      }
    },
    // 解绑文字提示
    handleClearTextPattern() {
      const { mapRef } = props
      mapRef.value.clearEvents('mouseover')
      mapRef.value.clearEvents('mousemove')
      mapRef.value.clearEvents('mouseout')
      mapRef.value.clearEvents('click')
      mapRef.value.remove(eventState.textPattern)
      eventState.textPattern!.hide()
      eventState.textPattern!.remove()
      eventState.textPattern = undefined
    },
    // 修改文字提示
    handleChangeTextPrompt() {
      // 更新提示文案
      const clickNum = eventState.textPattern!.getExtData() + 1
      eventState.textPattern!.setExtData(clickNum)
      eventState.textPattern!.setText(clickNum === 1 ? '单击以继续绘制' : '鼠标右键完成操作')
    },
    // 创建鼠标跟随文字提示
    handleCreateMouseFollowText() {
      const { mapRef, aMapRef } = props
      eventState.textPattern = new aMapRef.value.Text({
        map: mapRef.value,
        offset: [3, 3],
        bubble: true,
        text: '单击开始绘制',
        visible: false,
        extData: 0
      })
      // 为文案绑定跟踪鼠标事件
      mapRef.value.on('mouseover', (e: { lnglat: { lng: number; lat: number } }) => {
        eventState.textPattern!.setPosition(e.lnglat)
        eventState.textPattern!.show()
      })
      mapRef.value.on('mousemove', (e: { lnglat: { lng: number; lat: number } }) => {
        eventState.textPattern!.setPosition(e.lnglat)
      })
      mapRef.value.on('mouseout', () => {
        eventState.textPattern!.hide()
      })
    },
    // 创建鼠标工具并设置折线绘制
    handleCreateMouseToolPolyline(clear = true) {
      const { mapRef, aMapRef } = props
      eventState.mouseTool = new aMapRef.value.MouseTool(mapRef.value)
      // 只有在初始化折线的时候才会配置默认是否展示visible
      eventState.mouseTool?.polyline({
        ...polylineOptions,
        strokeColor: props.strokeColor,
        extData: { visible: true }
      })
      // 更新画折线文案
      mapRef.value.on('click', eventMethod.handleChangeTextPrompt)
      eventState.mouseTool!.on('draw', (e) => {
        if (!e?.obj) return
        const path = e.obj.getPath()
        if (path?.length <= 1) return
        // 设置新的折线图案
        setCurrentPatternPath(e.obj)
        // 清除鼠标工具后重新设置
        eventMethod.handleClearMouseTool(clear)
        // 重制文案状态
        eventMethod.handleClearTextPattern()
        eventMethod.handleCreateMouseFollowText()
        eventState.textPattern!.show()
        // 重新设置绘折线
        eventMethod.handleCreateMouseToolPolyline()
      })
    },
    // 解绑鼠标工具并至空
    handleClearMouseTool(clear = false) {
      const { mapRef } = props
      mapRef.value?.clearEvents('')
      eventState.mouseTool?.close(clear)
      eventState.mouseTool = undefined
    },
    // 绘制折线图案
    handleMapDrawPattern() {
      // if (eventState.mouseTool) {
      //   // 清除上一步没保存绘制的图像
      //   eventMethod.handleClearMouseTool(true)
      //   return
      // }
      // 创建提示文本
      eventMethod.handleCreateMouseFollowText()
      // 只有画第一个面的时候才保存 其他的都清空
      eventMethod.handleCreateMouseToolPolyline(false)
    },
    // 修改绘制的折线路径点（关联路灯，配电设施专用）
    handleChangeDrawPolylinePath(position) {
      if (!eventState.mouseTool) return
      const polylines = eventState.mouseTool?.overlays?.polyline
      const path = polylines?.[0]?.getPath()
      // 如果是初始点 则重置初始点点位
      if (!polylines?.length) {
        nextTick(() => {
          if (polylines?.length) {
            polylines?.[0]?.setPath([position, position])
          }
        })
        return
      }
      // if (!path) {
      //   // ElMessage.warning('请至少绘制一条直线后再关联该点。')
      //   return
      // }
      // 移除点击的最后一个点
      path.pop()
      // 把新点击的点于旧的合并整合
      polylines?.[0]?.setPath(path?.concat([position]))
    },
    // 关闭当前编辑折线图案
    handleCloseEditPattern(drawPatterns) {
      if (eventState.patternEditor) {
        eventState.patternEditor.close()
        eventState.patternEditor = undefined
        // 因为高德地图多线bug问题 所以在编辑后需要重新设置一遍线的样式
        if (drawPatterns)
          drawPatterns?.setOptions({ ...polylineOptions, strokeColor: props.strokeColor })
      }
    },
    // 编辑当前折线图案
    handleMapEditPattern(pattern) {
      const { mapRef, aMapRef } = props
      eventState.patternEditor = new aMapRef.value.PolylineEditor(mapRef.value, pattern)
      eventState.patternEditor?.open()
    },
    // 根据折线路径和面路径进行处理并返回处理后的数据
    handlePolylinePatternWithCropPattern(polylinePath, cropPath) {
      const { aMapRef } = props
      const lineFilterPath: Position[] = polylinePath?.map?.((item) => [item.lng, item.lat])
      const cropFilterPath: Position[] = cropPath?.map?.((item) => [item.lng, item.lat])
      if (
        !aMapRef.value.GeometryUtil.doesLineRingIntersect(lineFilterPath, cropFilterPath) &&
        !aMapRef.value.GeometryUtil.isPointInRing(lineFilterPath[0], cropFilterPath)
      ) {
        return {
          type: 'polyline',
          positions: lineFilterPath
        }
      }
      cropFilterPath.push(cropFilterPath[0])
      const line = lineString(lineFilterPath)
      const poly = polygon([cropFilterPath])
      const splitter = lineString(cropFilterPath)
      const splitLine = lineSplit(line, splitter)
      const intersects = lineIntersect(line, splitter)?.features?.map(
        (item) => item?.geometry?.coordinates
      )
      const intersectsStr = intersects.toString()
      const filterSplitLine = splitLine?.features
        ?.map((item) => {
          const path = item?.geometry?.coordinates
          const flag = booleanWithin(item, poly)
          const eachPointInpolyFlag = path?.every((pathItem) =>
            intersectsStr?.includes(pathItem?.toString())
          )
          // 判断 每个分割出来的线的首尾点是否在面内 在的话 则return false
          if ((flag && eachPointInpolyFlag) || booleanContains(poly, item)) return undefined
          return path
        })
        ?.filter(Boolean) as Position[][]
      return {
        type: 'multiPolyline',
        positions: filterSplitLine
      }
    },
    // 剪切当前折线图案
    handleMapCropPattern(drawPattern, closeCropCallback) {
      const { mapRef, aMapRef } = props
      eventState.mouseTool = new aMapRef.value.MouseTool(mapRef.value)
      eventState.mouseTool?.polygon({
        strokeColor: styles.dangerColor,
        fillColor: styles.dangerColor
      })
      eventState.mouseTool!.on('draw', (e) => {
        if (!e?.obj) return
        const cropPath = e.obj.getPath()
        e.obj.hide()
        if (cropPath?.length <= 2) {
          // 关闭剪切
          closeCropCallback(undefined)
          return
        }
        let patternNewPath
        if (drawPattern.type === 'polyline') {
          const polylinePattern = eventMethod.handlePolylinePatternWithCropPattern(
            drawPattern.pattern.getPath(),
            cropPath
          )
          patternNewPath = polylinePattern.positions
          drawPattern.type = patternNewPath?.length ? polylinePattern.type : 'polyline'
        } else {
          patternNewPath = drawPattern.pattern
            .getPath()
            ?.map((path: MapToolBarLngLatType[]) => {
              const polylinePattern = eventMethod.handlePolylinePatternWithCropPattern(
                path,
                cropPath
              )
              return polylinePattern?.type === 'polyline'
                ? [polylinePattern.positions]
                : polylinePattern.positions
            })
            ?.filter((filterItem: Position[]) => filterItem.length)
            ?.flat()
          drawPattern.type = patternNewPath?.length ? 'multiPolyline' : 'polyline'
        }
        if (!patternNewPath?.length) {
          drawPattern.pattern.setExtData({ visible: false })
          drawPattern.pattern.setPath([
            [0, 0],
            [0, 0]
          ])
          drawPattern.pattern.hide()
        } else {
          drawPattern.pattern.setPath(patternNewPath)
        }
        // 关闭剪切
        closeCropCallback(undefined)
      })
    },
    // 连接点到折线上（关联路灯，配电设施专用）
    handleContactPointAtPolyline(position) {
      if (eventState.contactLinkPattern) {
        const path = eventState.contactLinkPattern?.getPath() || []
        // 如果最后一个点跟新录入的点一样则停止录入
        if (
          path?.length &&
          path[path?.length - 1].lng === position.lng &&
          path[path?.length - 1].lat === position.lat
        )
          return
        eventState.contactLinkPattern.setPath(path?.concat([position]))
        // 更新提示文本
        eventMethod.handleChangeTextPrompt()
      }
    },
    // 连线新的折线图案
    handleMapContactLinkPattern() {
      const { mapRef, aMapRef, strokeColor } = props
      // 初始化折线需要visible为true否则第二条线会出问题
      eventState.contactLinkPattern = new aMapRef.value.Polyline({
        ...polylineOptions,
        strokeColor,
        extData: { visible: true }
      })
      mapRef.value.add(eventState.contactLinkPattern)
      mapRef.value.on('rightclick', () => {
        const contactLinkPatternPath = eventState.contactLinkPattern?.getPath()
        if (!contactLinkPatternPath || contactLinkPatternPath?.length < 2) return
        setCurrentPatternPath(eventState.contactLinkPattern!)
        // 重制提示文本
        eventState.textPattern!.setExtData(0)
        eventState.textPattern!.setText('单击开始绘制')
        // 清除事件 重新注册
        mapRef.value.clearEvents('rightclick')
        eventMethod.handleMapContactLinkPattern()
      })
    },
    // 初始化折线
    handleInitPolylinePattern(strokeColor, path) {
      const { mapRef, aMapRef } = props
      return new aMapRef.value.Polyline({
        ...polylineOptions,
        path,
        map: mapRef.value,
        strokeColor,
        extData: { visible: true }
      })
    }
  }

  return [eventState, eventMethod]
}
